#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
API请求日志模块
用于记录API请求和响应
"""

import logging
import time
import json
import functools
import traceback
from django.utils.deprecation import MiddlewareMixin
from django.http import HttpRequest, HttpResponse, JsonResponse

# 获取API操作日志记录器
api_logger = logging.getLogger('api')


class APILoggingMiddleware(MiddlewareMixin):
    """
    API日志中间件，记录所有API请求和响应
    """
    
    def __init__(self, get_response=None):
        super().__init__(get_response)
        self.get_response = get_response
        
    def process_request(self, request):
        # 为请求对象添加开始时间
        request.start_time = time.time()
        
        # 记录请求信息
        if not request.path.startswith('/static/') and not request.path.startswith('/media/'):
            api_logger.info(f"Request: {request.method} {request.path}")
            
            # 记录请求头信息
            headers = {k: v for k, v in request.META.items() if k.startswith('HTTP_')}
            api_logger.debug(f"Headers: {json.dumps(headers, default=str)}")
            
            # 记录GET参数
            if request.GET:
                api_logger.debug(f"GET Params: {json.dumps(dict(request.GET), default=str)}")
            
            # 记录POST参数（非文件上传）
            if request.method == 'POST' and not request.FILES:
                try:
                    if request.body:
                        if request.content_type and 'application/json' in request.content_type:
                            body = json.loads(request.body)
                            # 过滤掉敏感信息
                            if isinstance(body, dict):
                                filtered_body = {k: v for k, v in body.items() 
                                              if not (k.lower() in ['password', 'token', 'secret'])}
                                api_logger.debug(f"Request Body: {json.dumps(filtered_body, default=str)}")
                        else:
                            api_logger.debug(f"Request Body: [Binary data or form data]")
                except Exception as e:
                    api_logger.warning(f"Failed to log request body: {str(e)}")
        
        return None
    
    def process_response(self, request, response):
        # 记录响应信息
        if hasattr(request, 'start_time') and not request.path.startswith('/static/') and not request.path.startswith('/media/'):
            # 计算处理时间
            duration = time.time() - request.start_time
            status_code = getattr(response, 'status_code', 0)
            
            api_logger.info(f"Response: {request.method} {request.path} - {status_code} in {duration:.2f}s")
            
            # 记录响应内容（仅JSON响应）
            if isinstance(response, JsonResponse) or (hasattr(response, 'content_type') and 'application/json' in response.content_type):
                try:
                    if hasattr(response, 'content'):
                        content = json.loads(response.content.decode('utf-8'))
                        # 记录简要响应
                        if 'code' in content:
                            api_logger.debug(f"Response Code: {content.get('code')}")
                        if 'message' in content:
                            api_logger.debug(f"Response Message: {content.get('message')}")
                except Exception as e:
                    api_logger.warning(f"Failed to log response content: {str(e)}")
        
        return response
    
    def process_exception(self, request, exception):
        # 记录异常信息
        api_logger.error(f"Exception in {request.method} {request.path}: {str(exception)}")
        api_logger.error(traceback.format_exc())
        return None


def log_api_call(func):
    """
    API调用日志装饰器，用于视图函数
    """
    @functools.wraps(func)
    def wrapper(request, *args, **kwargs):
        start_time = time.time()
        
        # 记录请求信息
        api_logger.info(f"API Call: {func.__name__}")
        
        # 记录GET参数
        if request.GET:
            api_logger.debug(f"GET Params: {json.dumps(dict(request.GET), default=str)}")
        
        # 记录POST参数（非文件上传）
        if request.method == 'POST' and not request.FILES:
            try:
                if request.body:
                    if request.content_type and 'application/json' in request.content_type:
                        body = json.loads(request.body)
                        # 过滤掉敏感信息
                        if isinstance(body, dict):
                            filtered_body = {k: v for k, v in body.items() 
                                          if not (k.lower() in ['password', 'token', 'secret'])}
                            api_logger.debug(f"Request Body: {json.dumps(filtered_body, default=str)}")
            except Exception as e:
                api_logger.warning(f"Failed to log request body: {str(e)}")
        
        try:
            # 执行原视图函数
            response = func(request, *args, **kwargs)
            
            # 计算处理时间
            duration = time.time() - start_time
            
            # 记录响应信息
            status_code = getattr(response, 'status_code', 0)
            api_logger.info(f"API Response: {func.__name__} - {status_code} in {duration:.2f}s")
            
            return response
            
        except Exception as e:
            # 记录异常信息
            api_logger.error(f"Exception in {func.__name__}: {str(e)}")
            api_logger.error(traceback.format_exc())
            raise
    
    return wrapper 